#!/bin/bash
### The script does kuberentes deployment of gitlab and its pre dependent components
### The respective kubectl configs are in k8s/gitlab/ location
### This is called in bin/k8s-review-deploy

# Change to the repository root folder via the scripts location
cd "$(dirname "$0")"/..
. k8s/includes/log
. k8s/includes/ci-environment
. k8s/includes/gitlab-health
. k8s/includes/gitlab-settings
########################################
set -x  # output all commands
set -o  pipefail
set -e  # exit on immediately on every error
set -u  # error on usage of undefined variables
########################################

### Need to move it to another file if required
# The INSTANCE_HOST variable represents the full URL to the EC2 instance MLReef is running on
# e.g: 'ec2-3-126-88-77.eu-central-1.compute.amazonaws.com'
# This Information is necessary so that e.g. the runners know where to find the backend
INSTANCE_HOST=$(cat out/instance.info)

# Only Used during deployment for gitlab configuration and runner configuration
# The gitlab server always serves port 80 locally. By setting the GITLAB_PORT variable,
# we let gitlab know, that the container's port 80 is mapped differently from the outside.
GITLAB_PORT=10080

# Used by the backend to connect to gitlab
# The hostname 'gitlab' is created by the local docker network
# The port used here must be the same as GITLAB_PORT
GITLAB_ROOT_URL=http://gitlab:$GITLAB_PORT

# The GITLAB_ADMIN_TOKEN is shared between Gitlab and the Backend
GITLAB_ADMIN_TOKEN=$GITLAB_ADMIN_TOKEN

# These secrets are used by Gitlab to encrypt passwords and tokens
# Changing them will invalidate the GITLAB_ADMIN_TOKEN as well as all other tokens
GITLAB_SECRETS_SECRET_KEY_BASE=secret1111111111122222222222333333333334444444444555555555566666666661234
GITLAB_SECRETS_OTP_KEY_BASE=secret1111111111122222222222333333333334444444444555555555566666666661234
GITLAB_SECRETS_DB_KEY_BASE=secret1111111111122222222222333333333334444444444555555555566666666661234


# This is the docker tag that will be used for starting EPF pipelines
EPF_IMAGE_TAG=$CI_COMMIT_REF_SLUG
# THe internal connection URL for the EPF runners to connect to the backend
EPF_BACKEND_URL=http://backend.$INSTANCE_HOST
# THe internal connection URL for the EPF runners to connect to the gitlab
EPF_GITLAB_URL=http://gitlab.$INSTANCE_HOST
EPF_GITLAB_FORCE_PORT=80
EPF_GITLAB_FORCE_PROTOCOL=http
# This is the docker tag that will be used for starting Experiment pipelines
EXPERIMENT_IMAGE_TAG=$CI_COMMIT_REF_SLUG

# App password used for the noreply@mlreef.com account
NOREPLY_EMAIL=${NOREPLY_EMAIL-}
NOREPLY_EMAIL_PASSWORD=${NOREPLY_EMAIL_PASSWORD-}

# Local configmap that would be used by gitlab, backend and gateway pods
cat > local-config-${CI_ENVIRONMENT_SLUG}.yml << LOCALCONF
apiVersion: v1
kind: ConfigMap
metadata:
  name: local-config
  labels:
    app: local-config-$CI_PROJECT_NAME
    ref: $CI_ENVIRONMENT_SLUG

data:
  INSTANCE_HOST: "$INSTANCE_HOST"
  GITLAB_PORT: "$GITLAB_PORT"
  GITLAB_ROOT_URL: "$GITLAB_ROOT_URL"
  GITLAB_ADMIN_TOKEN: "$GITLAB_ADMIN_TOKEN"
  GITLAB_SECRETS_SECRET_KEY_BASE: "$GITLAB_SECRETS_SECRET_KEY_BASE"
  GITLAB_SECRETS_OTP_KEY_BASE: "$GITLAB_SECRETS_OTP_KEY_BASE"
  GITLAB_SECRETS_DB_KEY_BASE: "$GITLAB_SECRETS_DB_KEY_BASE"
  EPF_IMAGE_TAG: "$EPF_IMAGE_TAG"
  EPF_BACKEND_URL: "$EPF_BACKEND_URL"
  EPF_GITLAB_URL: "$EPF_GITLAB_URL"
  EPF_GITLAB_FORCE_PORT: "$EPF_GITLAB_FORCE_PORT"
  EPF_GITLAB_FORCE_PROTOCOL: "$EPF_GITLAB_FORCE_PROTOCOL"
  IMAGE_TAG: "$IMAGE_TAG"
  EXPERIMENT_IMAGE_TAG: "$EXPERIMENT_IMAGE_TAG"
  LOCAL_EPF_IMAGE_PATH: "$LOCAL_EPF_IMAGE_PATH"
  # LOCAL_EXPERIMENT_IMAGE_PATH has been not set to local registry temporarily as k8s runner has issue in pulling it as base image
  # Due to insecure registry. Once gitlab moves to https, it can be fixed as below :
  # LOCAL_EXPERIMENT_IMAGE_PATH: "$LOCAL_EXPERIMENT_IMAGE_PATH"
  # As it is not set, backend will use the default value from application.yml which reads from gitlab.com registry

  # Set PIP_SERVER to blank. In Nautilus, it could be used to local pip server to run Nautilus in offline mode
  PIP_SERVER: ""

LOCALCONF

cat local-config-${CI_ENVIRONMENT_SLUG}.yml
kubectl apply -f local-config-${CI_ENVIRONMENT_SLUG}.yml

## Create the tls secret for ingress controller.
## openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /tmp/tls.key -out /tmp/tls.crt -subj "/CN=35.246.253.255.nip.io"
## cat /tmp/tls.crt | base64 -w 0
## cat /tmp/tls.key | base64 -w 0
## Add them in Gitlab variable
## and the same is being used for all the review environments
cat > review-deploy-tls-${CI_ENVIRONMENT_SLUG}.yml << LOCALCONF
apiVersion: v1
kind: Secret
metadata:
  name: review-deploy-tls
type: kubernetes.io/tls
data:
  tls.crt: $DEV_INGRESS_TLS_CRT
  tls.key: $DEV_INGRESS_TLS_KEY
LOCALCONF

cat review-deploy-tls-${CI_ENVIRONMENT_SLUG}.yml
kubectl apply -f review-deploy-tls-${CI_ENVIRONMENT_SLUG}.yml

## Apply finally generate yml file from bin/k8s-review-deploy => k8s/prepare-final-deployment-yml
kubectl apply -f gitlab-${dashed_domain}.yml

# Ingress deployment ( gitlab endpoint should be up before further steps)
kubectl apply -f ingress-${dashed_domain}.yml


## Verify if gitlab is up
waitUntilGitlabAvailable

log "Ensuring availability of the Gitlab API to start"
until [ "$(checkGitlabPort /api/v4/projects)" = "200" ]; do
  printf '.'
  sleep 5;
done
log "Expecting code 200; received: $(checkGitlabPort /api/v4/projects)"
log "Waiting for Gitlab Runners API. The runners API is running in a separate process from the normal API"
until [ "$(checkGitlabPort /runners)" = "302" ]; do
  printf '.'
  sleep 5;
done
log "Expecting code 302; received: $(checkGitlabPort /runners)"

gitlab_pod_name=$(kubectl get pods --selector=app=gitlab-$CI_PROJECT_NAME | grep gitlab | awk '{print $1}')
log "2. Deleting all API tokens for root user (id=1)"
# http://gitlab.com/help/administration/troubleshooting/gitlab_rails_cheat_sheet.md
# Alternatively the token digest can be computed as follows:
# salt=$(echo $GITLAB_SECRETS_DB_KEY_BASE | cut -c1-32)
# token=$GITLAB_ADMIN_TOKEN$salt
# token_digest=$(echo $token | openssl sha256 -binary | base64 -)
kubectl exec -it $gitlab_pod_name -- sh -c "$(cat << EOM
  gitlab-rails runner -e production "
    User.find(1).personal_access_tokens.each do |cur|
      cur.delete
    end
  "
EOM
)"
log "Creating Admin API token $GITLAB_ADMIN_TOKEN. This might take up to 5 minutes"
kubectl exec -it $gitlab_pod_name -- sh -c "$(cat << EOM
  gitlab-rails runner -e production "User.find(1).personal_access_tokens.create(
    name: 'admin-api-token',
    token_digest: Gitlab::CryptoHelper.sha256('$GITLAB_ADMIN_TOKEN'),
    impersonation: false,
    scopes: [:api,:sudo]
  )"
EOM
)" #end of $(cat …)

#Change gitlab default setting
setMaxArtifactSizeForGitlab
setMaxAttachmentSizeForGitlab
setContainerRegistryTokenExpireDelayForGitlab

###gitlab local group and project creation###
export GITLAB_ROOTGROUP=$MLREEF_GITLAB_LOCAL_REGISTRY_GROUP
export GITLAB_PROJECT=$MLREEF_GITLAB_LOCAL_REGISTRY_PROJECT

#creating root group # 
rootGroupId=$(curl --header "PRIVATE-TOKEN: $GITLAB_ADMIN_TOKEN" "gitlab.${INSTANCE_HOST}/api/v4/groups?search=$GITLAB_ROOTGROUP" | jq -M 'map(select(.name == "'$GITLAB_ROOTGROUP'"))| .[0].id' )
if [ $rootGroupId == "null" ]; then
  rootGroupId=$(curl --request POST --header "PRIVATE-TOKEN: $GITLAB_ADMIN_TOKEN" --header "Content-Type: application/json" \
  --data '{"path": "'$GITLAB_ROOTGROUP'", "name": "'$GITLAB_ROOTGROUP'", "visibility": "public" ,"lfs_enabled": "true" , "description": "Root Group" }' \
  "gitlab.${INSTANCE_HOST}/api/v4/groups/" | jq '.["id"]')
fi
echo "Root group Id: $rootGroupId"
#project creation # 
projectId=$(curl "gitlab.${INSTANCE_HOST}/api/v4/groups/$rootGroupId/projects?search=$GITLAB_PROJECT" -H "PRIVATE-TOKEN: $GITLAB_ADMIN_TOKEN" | jq -M 'map(select(.name == "'$GITLAB_PROJECT'"))| .[0].id'  )
if [ $projectId == "null" ]; then
  projectId=$(curl --request POST --header "PRIVATE-TOKEN: $GITLAB_ADMIN_TOKEN" --header "Content-Type: application/json" \
  --data '{"path": "'$GITLAB_PROJECT'", "namespace_id": "'$rootGroupId'", "visibility": "public"}' \
  "gitlab.${INSTANCE_HOST}/api/v4/projects/" | jq '.["id"]')
fi
echo "Project Id: $projectId" 


